package com.tudouji.project.bill.service.impl;

import com.flow.service.pojo.BasePojo;
import com.flow.service.pojo.ResultParam;
import com.flow.service.pojo.flow.FlowTempNode;
import com.flow.service.pojo.result.FlowResult;
import com.flow.service.process.service.IFlowBaseService;
import com.flow.service.process.service.impl.CallBackParameterWrapper;
import com.flow.service.process.service.impl.FlowProcessProxy;
import com.github.pagehelper.PageHelper;
import com.tudouji.common.utils.DateUtils;
import com.tudouji.common.utils.IdUtils;
import com.tudouji.common.utils.SecurityUtils;
import com.tudouji.common.utils.StringUtils;
import com.tudouji.common.utils.sql.SqlUtil;
import com.tudouji.framework.web.domain.AjaxResult;
import com.tudouji.framework.web.page.PageDomain;
import com.tudouji.framework.web.page.TableSupport;
import com.tudouji.project.bill.domain.Recharge;
import com.tudouji.project.bill.domain.Sellform;
import com.tudouji.project.bill.mapper.RechargeMapper;
import com.tudouji.project.bill.mapper.SellformMapper;
import com.tudouji.project.bill.service.IRechargeService;
import com.tudouji.project.bill.service.ISellformService;
import com.tudouji.project.customer.domain.Cashflow;
import com.tudouji.project.customer.domain.Customer;
import com.tudouji.project.customer.mapper.CashflowMapper;
import com.tudouji.project.customer.mapper.CustomerMapper;
import com.tudouji.project.flow.service.impl.FlowtempnodeServiceImpl;
import com.tudouji.project.flow.utils.FlowProcessUtil;
import com.tudouji.project.organization.domain.Department;
import com.tudouji.project.organization.mapper.DepartmentMapper;
import com.tudouji.project.pay.domain.SfPrebalanceRecord;
import com.tudouji.project.pay.mapper.SfPrebalanceRecordMapper;
import com.tudouji.project.pay.service.ISfPrebalanceRecordService;
import com.tudouji.project.permission.domain.Salespermission;
import com.tudouji.project.permission.service.impl.SalespermissionServiceImpl;
import com.tudouji.project.system.domain.SysUser;
import com.tudouji.project.system.service.impl.BusinesscodeServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.ConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.List;

/**
 * 充值报表Service业务层处理
 *
 * @author wf
 * @date 2021-04-15
 */
@Slf4j
@Service
public class RechargeServiceImpl implements IRechargeService, IFlowBaseService {
    @Autowired
    private RechargeMapper rechargeMapper;
    @Autowired
    private SellformMapper sellformMapper;
    @Autowired
    private ISellformService sellformService;
    @Autowired
    private FlowtempnodeServiceImpl iFlowtempnodeService;
    @Autowired
    private SalespermissionServiceImpl permissionService;
    @Autowired
    private FlowProcessUtil processUtils;
    @Autowired
    private FlowProcessProxy processProxy;
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private BusinesscodeServiceImpl codeService;
    @Autowired
    private CashflowMapper cashflowMapper;
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private SfPrebalanceRecordMapper sfPrebalanceRecordMapper;
    @Autowired
    private ISfPrebalanceRecordService prebalanceRecordService;

    /**
     * 设置请求分页数据
     */
    protected void startPage() {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            PageHelper.startPage(pageNum, pageSize, orderBy);
        }
    }

    /**
     * 查询充值报表
     *
     * @param guid 充值报表ID
     * @return 充值报表
     */
    @Override
    public Recharge selectRechargeById(String guid) {
        return rechargeMapper.selectRechargeById(guid);
    }
    @Override
    public Recharge selectRechargeByNewId(Long id) {
        return rechargeMapper.selectRechargeByNewId(id);
    }

    /**
     * 查询充值报表列表
     *
     * @param recharge 充值报表
     * @return 充值报表
     */
    @Override
    public List<Recharge> selectRechargeList(Recharge recharge, String status, String functionType) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        if (recharge == null) {
            recharge = new Recharge();
        }
//        recharge.setFlowid("37");
        if (org.apache.commons.lang.StringUtils.isNotBlank(status)) {
            // 待处理
            if (status.equals("00")) {
                startPage();
                recharge.setCreateBy(sysUser.getUserId());
                return rechargeMapper.selectApplyPendingList(recharge);
            } else {
                String[] sts = status.split(",");
                Integer[] stss = (Integer[]) ConvertUtils.convert(sts, Integer.class);
                recharge.setStats(stss);
            }
        }
        //查询是否有全局权限
        List<Salespermission> permissions = permissionService.getPermByScAndFuncSYS(sysUser.getUserId(), functionType, "4");
        if (permissions.size() > 0) {
            startPage();
            return rechargeMapper.selectRechargeList(recharge);
        } else {
            recharge.setCreateBy(sysUser.getUserId());
            //是否有部门权限
            permissions = permissionService.getPermByScAndFuncSYS(sysUser.getUserId(), functionType, "2");

            startPage();
            if (permissions.size() > 0) {
                String[] deptids = new String[permissions.size()];
                for (int i = 0; i < permissions.size(); i++) {
                    deptids[i] = permissions.get(i).getDepartid();
                }
                recharge.setDeptIds(deptids);
                return rechargeMapper.selectApplyListByPerm(recharge);
            } else {
                //查询个人的
                return rechargeMapper.selectApplyListByUser(recharge);
            }
        }
    }

    /**
     * 新增充值报表
     *
     * @param recharge 充值报表
     * @return 结果
     */
    @Override
    public int insertRecharge(Recharge recharge) {
        return rechargeMapper.insertRecharge(recharge);
    }

    /**
     * 修改充值报表
     *
     * @param recharge 充值报表
     * @return 结果
     */
    @Override
    public int updateRecharge(Recharge recharge) {
        return rechargeMapper.updateRecharge(recharge);
    }

    /**
     * 批量删除充值报表
     *
     * @param guids 需要删除的充值报表ID
     * @return 结果
     */
    @Override
    public int deleteRechargeByIds(String[] guids) {
        return rechargeMapper.deleteRechargeByIds(guids);
    }

    /**
     * 删除充值报表信息
     *
     * @param guid 充值报表ID
     * @return 结果
     */
    @Override
    public int deleteRechargeById(String guid) {
        return rechargeMapper.deleteRechargeById(guid);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public AjaxResult save(Recharge recharge, Long deptId, String fileIds, Long taskid, String opinion) {
        SysUser user = SecurityUtils.getLoginUser().getUser();

        //检查预收款 是否为负数
        /*AjaxResult error = checkPrebalance(recharge);
        if (error != null) {
            return error;
        }*/
        prepareRecharge(recharge, user);

        FlowResult result = processUtils.defaultStart(processUtils.getStartNode(Long.valueOf(recharge.getFlowid())), recharge, fileIds, user);
        if (result.getMsg().equals(ResultParam.SUCCESS)) {
            Recharge pb = new Recharge();
            pb.setStatus(result.getNextStat());
            pb.setGuid(recharge.getGuid());
            this.updateRecharge(pb);
            return AjaxResult.success();
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(result.getMsg());
        }
    }

    public void prepareRecharge(Recharge recharge, SysUser user) {
        recharge.setOperator(user.getNickName());
        recharge.setOperatorid(user.getTuserId());
        recharge.setCreateBy(user.getUserId());
        recharge.setFlowid("37");
        recharge.setFlag(1);
        recharge.setStatus(-1);
        recharge.setApplyamount(recharge.getAmount());
        recharge.setCreatetime(DateUtils.getNowDate());
        String code = codeService.getCode("10");
        recharge.setCode(code);
        String guid = IdUtils.fastSimpleUUID();
        recharge.setGuid(guid);
        Department department = departmentMapper.selectDepartmentById(recharge.getDepartid());
        recharge.setDeptId(department.getId());
        rechargeMapper.insertRecharge(recharge);
    }

    private AjaxResult checkPrebalance(Recharge recharge) {
        Customer cust = customerMapper.selectCustomerById(recharge.getCustomerid());
        BigDecimal currPrebalance = cust.getCurrprebalance() == null ? BigDecimal.ZERO : cust.getCurrprebalance();
        if (recharge.getType() == 1) {
            if (recharge.getAmount().add(currPrebalance).compareTo(BigDecimal.ZERO) == -1) {
                return AjaxResult.error("余额不足！");
            }
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public AjaxResult approval(Long id, Long taskid, String opinion, String fileIds) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        Recharge recharge = rechargeMapper.selectRechargeByNewId(id);

        Department department = departmentMapper.selectDepartmentById(recharge.getDepartid());
        recharge.setDeptId(department.getId());

        FlowResult result = processUtils.defaultApproval(taskid, fileIds, opinion, recharge
                , sysUser);
        if (result.getMsg().equals(ResultParam.SUCCESS)) {
            Recharge pb = new Recharge();
            pb.setStatus(result.getNextStat());
            pb.setGuid(recharge.getGuid());
            this.updateRecharge(pb);
            return AjaxResult.success();
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(result.getMsg());
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public AjaxResult recharge(Long id, Long taskid, String opinion, String fileIds) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        Recharge recharge = rechargeMapper.selectRechargeByNewId(id);
        Customer cust = customerMapper.selectCustomerById(recharge.getCustomerid());

        if (recharge.getFlag() == 2) {//退款需要扣钱 转为负数
            recharge.setAmount(recharge.getAmount().negate());//批准金额
        }

        //检查预收款 是否为负数
        /*AjaxResult error = checkPrebalance(recharge);
        if (error != null) {
            return error;
        }*/
        // 写入充值记录 ,更新预付款余额
        Cashflow cashflow = new Cashflow();
        cashflow.setCustomerid(recharge.getCustomerid());
        cashflow.setCode(recharge.getCode());
        cashflow.setLinkid(recharge.getGuid());
        cashflow.setAmount(recharge.getAmount());
        cashflow.setPrebalance(
                recharge.getAmount().add(cust.getPrebalance() == null ? BigDecimal.ZERO : cust.getPrebalance()));
        cashflow.setType(recharge.getType());
        String guid = IdUtils.fastSimpleUUID();
        cashflow.setGuid(guid);
        cashflow.setOperatorid(recharge.getOperatorid());
        cashflow.setOperator(recharge.getOperator());
        cashflow.setCreatetime(DateUtils.getNowDate());
        cashflowMapper.insertCashflow(cashflow);

        // 更新余额
        Customer customer = new Customer();
        customer.setGuid(recharge.getCustomerid());
        customer.setPrebalance((cust.getPrebalance() == null ? BigDecimal.ZERO : cust.getPrebalance())
                .add(recharge.getAmount() == null ? BigDecimal.ZERO : recharge.getAmount()));
        customer.setCurrprebalance((cust.getCurrprebalance() == null ? BigDecimal.ZERO : cust.getCurrprebalance())
                .add((recharge.getAmount() == null ? BigDecimal.ZERO : recharge.getAmount())));
        customerMapper.updateCustomer(customer);
        Department department = departmentMapper.selectDepartmentById(recharge.getDepartid());
        recharge.setDeptId(department.getId());

        FlowResult result = processUtils.defaultApproval(taskid, fileIds, opinion, recharge
                , user);
        if (result.getMsg().equals(ResultParam.SUCCESS)) {
            Recharge pb = new Recharge();
            pb.setStatus(result.getNextStat());
            pb.setGuid(recharge.getGuid());
            this.updateRecharge(pb);
            return AjaxResult.success();
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(result.getMsg());
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public AjaxResult refuse(Long id, String fileIds, String opinion, Long taskid, Long refuseNodeid, Long backUserid) {
        Recharge recharge = rechargeMapper.selectRechargeByNewId(id);

        SysUser sysUser = SecurityUtils.getLoginUser().getUser();

        FlowResult result = processUtils.defaultRefuse(taskid, fileIds, opinion, recharge
                , sysUser, refuseNodeid, backUserid);

        if (result.getMsg().equals(ResultParam.SUCCESS)) {
            Recharge pb = new Recharge();
            pb.setStatus(result.getNextStat());
            pb.setGuid(recharge.getGuid());
            this.updateRecharge(pb);
            return AjaxResult.success();
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(result.getMsg());
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public AjaxResult del(Long id) {
        Recharge apply = rechargeMapper.selectRechargeByNewId(id);
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();

        Recharge recharge = new Recharge();
        recharge.setId(id);
        recharge.setStatus(0);
        rechargeMapper.updateRecharge(recharge);
        //更新待处理任务
        processUtils.updateTaskByOrderId(id, sysUser, Long.valueOf(apply.getFlowid()));
        return AjaxResult.success();
    }
    //TODO 充值流程财务确认节点完成后，新增回调：
    // 1、判断当前充值流程如果关联了销售订单，关联的销售订单为“上车付款”，查询该销售订单的“充值确认”待处理任务，有则自动完成该待处理任务，没有待处理任务则不做处理。
    // 2、当前充值订单如果关联了销售订单，充值完成后发起自动核销，账户余额充足的情况下完成对应销售订单的核销操作。
    // 3、当前充值订单没有关联销售订单的话，不做处理。
    @Transactional
    @Override
    public boolean callbackAfterFinish(CallBackParameterWrapper cbpw) {
        log.info(">>>>>>>>>>> recharge callbackAfterFinish start");
        SysUser user = SecurityUtils.getLoginUser().getUser();

        Recharge recharge = rechargeMapper.selectRechargeByNewId(cbpw.getBase().getId());
        Sellform sellform = new Sellform();
        sellform.setRechargeId(recharge.getId());
        sellform.setRechargeCode(recharge.getCode());
        List<Sellform> sellforms = sellformMapper.selectSellformList(sellform);
        if (sellforms.size() > 0){
            sellform = sellforms.get(0);
            if (sellform.getPaytype() == 2){
                FlowTempNode node = new FlowTempNode();
                node.setOrderId(sellform.getId());
//                node.setCreateBy(1L);
                node.setFlowId(Long.valueOf(sellform.getFlowtempguid()));
                List<FlowTempNode> nodes = iFlowtempnodeService.getPendingNodes(node);
                if (nodes.size() > 0){
                    sellformService.approval(sellform.getId(), nodes.get(0).getFlowTaskId(), null, null);
                    //????余额充足，核销
                    sellformService.settleHexiao(sellform, user);
                    SfPrebalanceRecord prebalanceRecord = new SfPrebalanceRecord();
                    prebalanceRecord.setSellformId(sellform.getId());
                    prebalanceRecord.setStats(new Integer[]{1, 2});
                    prebalanceRecord.setType(1);
                    List<SfPrebalanceRecord> records = sfPrebalanceRecordMapper.selectSfPrebalanceRecordList(prebalanceRecord);
                    for (int i = 0; i < records.size(); i++) {

                        prebalanceRecordService.hexiao(records.get(i));
                    }
                }
            }
        }
        log.info("recharge callbackAfterFinish end <<<<<<<<<<<<<");

        return true;
    }
    @Override
    public BasePojo getBaseById(Long id) {
        return selectRechargeByNewId(id);
    }

    @Override
    public BasePojo getBaseByCode(String code) {
        return null;
    }
}
